﻿<?xml version="1.0" encoding="utf-8" ?>
<document>
  <example>
    The following code demonstrates how you can create and add your own validation rule.
    <code>
      DtdSchema schema = DtdSchema.Load();
      SgmlDocument doc = new SgmlDocument(schema);
      SgmlValidatorSettings validatorSettings = doc.Settings.ValidatorSettings;
      validatorSettings.Rules.Add(new CustomRule(schema));
    </code>
    <code>
public class CustomRule : IValidationRule {
        private DtdSchema schema;

        public CustomRule(DtdSchema schema) {
            name = SName.Get("th");
            this.schema = schema;
            }

        private SName name;
        public SName Name {
            get { return name; }
            }

        public bool Ignore(SElement element, SElement ancestor) {
            return false;
            }

        public bool CanClose(SElement element, SElement endElement) {
            return (string.Equals(element.LocalName, endElement.LocalName, StringComparison.Ordinal) &amp;&amp;
                string.Equals(element.Prefix, endElement.Prefix, StringComparison.Ordinal));
            }

        public bool CanContain(SElement element, SElement ancestor) {
            return string.Equals(ancestor.LocalName, "tr", StringComparison.Ordinal);
            }

        public bool TrySurround(SElement element) {
            if (string.Equals(element.Parent.LocalName, "table", StringComparison.Ordinal))
                return true;
            else
                return false;
            }

        public bool CanSurround(SElement element) {
            if (TrySurround(element))
                return true;
            if (string.Equals(element.Parent.LocalName, "tbody", StringComparison.Ordinal))
                return true;
            else
                return false;
            }

        public bool Allocate(SElement element, IElementAllocator allocator) {
            return allocator.Allocate(element, AllocationModes.InPreviousSibling | AllocationModes.InAncestors | AllocationModes.InPreviousDescendants);
            }

        public bool Surround(SElement element, IElementAllocator allocator) {
            if (string.Equals(element.Parent.LocalName, "table", StringComparison.Ordinal)) {
                SElement tbody = new SElement("TBODY", schema.GetElementDeclaration("TBODY"));
                element.Parent.Add(tbody);
                SElement tr = new SElement("TR", schema.GetElementDeclaration("TR"));
                tbody.Add(tr);

                element.Remove();
                tr.Add(element);
                return true;
                }
            if (allocator.Allocate(element, AllocationModes.SurroundInAncestor))
                return true;
            else
                return false;
            }
        }
    </code>
  </example>
</document>
